import { configByID, gameConfig, gameConfigHandle, propName } from "js/config/gameConfig"
import utils from "js/core/utils"
import { FighterAttriModel, FighterModel, SkillModel } from "js/model/fighterModel"
import { ItemModel } from "js/model/itemModel"
import { PartnerModel } from "js/model/partnerModel"
import { PlayerModel } from "js/model/playerModel"
import { EquipmentItemType, HurtType, MapType, TownBuildType, TownEffects } from "js/typeDefine/typeDefine"
import equipmentHandle from "./equipmentHandle"
import fighterHandle from "./fighterHandle"
import gameUtils from "js/core/gameUtils"

let attriPoints = { maxHp: [0, 20], attack: [0, 1], attackSpeed: [0, 20], perAttri: [0, 5], normalAttri: [0, 1] }

const PartnerQualityRateText = ['C', 'B', 'A', 'S', 'SS', 'SSS']

class PartnerHandle {
    createPartnerFighter(player: PlayerModel, partner: PartnerModel, gameMode?) {
        let fighter = new FighterModel()
        let fighterAttri = new FighterAttriModel()
        fighter.attri = fighterAttri
        fighter.tID = partner.tID
        fighter.quality = partner.quality
        fighter.formationPos = partner.formationPos
        fighter.lvl = partner.lvl
        let attriList = gameConfigHandle.gameConfig.partner.attriList
        let partnerConfig = configByID[partner.tID]
        if (partnerConfig) {
            partnerConfig.attris.forEach(attri => {
                let attriName = attri[0]
                let value: any = attri[1]

                fighter.attri[attriName] += value
            })
        }
        let baseConfig = gameConfig.partner
        let attriFeature = partner.customFeature || partnerConfig.attriFeature
        // 星级强化
        let star = partner.star
        Object.entries(baseConfig.baseAttri).forEach(item => {
            let attriName = item[0]
            let startAttri = baseConfig.startAttri[attriName]
            let values: any = item[1]
            let value = utils.getIncValue(attriList[attriName], partner.lvl) * values[0] * values[1] + startAttri
            if (fighter.quality) {
                value = (1 + baseConfig.qualityAttriPoint[fighter.quality] / 100) * value
            }
            if (star) {
                value = Math.floor(value * (1 + star / 5))
            }
            let coe = attriFeature[attriName]
            let upValue = attriPoints[attriName] || (utils.getPerByAttri(attriName) == '%' ? attriPoints.perAttri : attriPoints.normalAttri)
            let coeLimite = utils.getIncValue(upValue, 5)
            if (coe > coeLimite) {
                coe = coeLimite
            }
            if (coe) {
                let isPer = (attriName == 'attackSpeed' || attriName == 'maxHp') ? true : utils.getPerByAttri(attriName) == '%'
                value = isPer ? value + coe : Math.floor(value * (1 + coe / 10))
            }
            fighter.attri[attriName] += value
        })

        //境界增加怒气上限
        let jjLvl = Math.floor((partner.lvl - 1) / 10) + 1
        let angerMaxUpByJjlvl = gameConfigHandle.gameConfig.partner.angerMaxUpByJjlvl
        let upAngerMaxMax = gameConfigHandle.gameConfig.partner.upAngerMaxMax
        let upAngerMax = utils.getIncValue(angerMaxUpByJjlvl, jjLvl - 1)
        if (upAngerMax > upAngerMaxMax) {
            upAngerMax = upAngerMaxMax
        }
        fighter.attri.angerMax += upAngerMax
        fighter.attri.hurtType = partnerConfig.hurtType || HurtType.Normal

        gameMode = gameMode || player.gameSet.gameMode
        this.calcEquipment(player, partner, fighter, gameMode)
        this.calcAttriStr(partner, fighter)
        this.getDefaultSkill(partner, fighter)
        this.calcTownAttri(player, fighter)
        fighterHandle.calcSkill(fighter)
        fighterHandle.calcTitles(player, fighter)
        if (!gameMode) {
            fighterHandle.calcTreasure(partner, fighter)
            fighterHandle.calcFormation(player, fighter)
        } else {
            fighter.attri.hit += 100
            fighterHandle.calcPosAttri(player, partner, fighter)
        }

        fighterHandle.calcBattleFighterAttri(fighter)
        fighterHandle.calcPower(partner, fighter)
        if (player.baseInfo.maxPower < fighter.power) {
            player.baseInfo.maxPower = fighter.power
        }
        fighter.hatredType = partnerConfig.hatredType || 1
        fighter.battleAttri.hp = fighter.battleAttri.maxHp
        fighter.battleAttri.attackLimit = partnerConfig.attackSpeedLimit == null ? true : partnerConfig.attackSpeedLimit
        return fighter
    }

    calcQualityRate(fig) {

    }

    calcTownAttri(player: PlayerModel, fighter: FighterModel) {
        // 城镇加成
        let townConfigList = gameConfig.town.list
        townConfigList.forEach(tc => {
            let effects = tc.effects
            let lvl
            if (tc.kind == TownBuildType.Town) {
                lvl = player.townInfo.lvl
            } else {
                lvl = player.townInfo.subBuildLvl[tc.kind]
            }
            let attriEffect = effects[TownEffects.AddPerOfAttri]
            if (attriEffect) {
                let v: any = attriEffect
                Object.entries(v).forEach(entry => {
                    let name = entry[0]
                    let v1: any = entry[1]
                    let value = utils.getIncValue(v1.values, lvl)
                    if (lvl >= v1.limitLvl) {
                        let attriName = name
                        let isPer = utils.getPerByAttri(attriName) == '%'
                        if (isPer) {
                            let key = attriName.replace('Per', '')
                            if (key == 'attack' || key == 'def' || key == 'maxHp') {
                                fighter.attri[key] = Math.floor((100 + value) / 100 * fighter.attri[key])
                            } else {
                                fighter.attri[key] = (100 + value) / 100 * fighter.attri[key]
                            }
                        } else {
                            fighter.attri[attriName] = Math.floor((100 + value) / 100 * fighter.attri[attriName])
                        }
                    }
                })

            }
        })
    }

    //属性强化属性计算
    calcAttriStr(partner: PartnerModel, fighter: FighterModel) {
        let attriStrLvls = partner.attriStrLvls
        let attris = gameConfigHandle.gameConfig.partner.attris
        let attriConfig = gameConfigHandle.gameConfig.partner.attriStr
        for (let i = 0; i < attris.length; i++) {
            let attriName = attris[i]
            if (attriStrLvls[attriName]) {
                let attriStrLvl = attriStrLvls[attriName] || 0
                let attriStrNum = utils.getIncValue(attriConfig[attriName], attriStrLvl)
                if (attriName == 'recoverHp' || attriName == 'critHurt') {
                    fighter.attri[attris[i]] += attriStrNum
                } else {
                    let v = (1 + attriStrNum / 100) * (fighter.attri[attriName] || 0)
                    fighter.attri[attris[i]] = utils.getPerByAttri(attriName) == '%' ? Number(v.toFixed(1)) : v
                }
            } else {
                attriStrLvls[attriName] = 0
            }
        }
    }

    //装备属性计算
    calcEquipment(player: PlayerModel, partner: PartnerModel, fighter: FighterModel, gameMode?) {
        let equipmentActive = gameMode ? equipmentHandle.getEquipmentActive(player, partner) : 0
        let equipments = partner.equipments[equipmentActive] || []
        gameConfigHandle.gameConfig.equipment.equipmentParts.forEach(part => {
            let equipment: ItemModel = equipments[part]
            if (equipment) {
                //主属性
                let attris = equipmentHandle.getAttriOfEquipment(equipment)
                for (let i = 0; i < attris.length; i++) {
                    fighter.attri[attris[i].attriName] += attris[i].attriValue
                }
                //把部位强化属性加进去
                let mainAttris = equipment.equipment.mainAttris
                let values = gameConfigHandle.gameConfig.equipment.partStrUpNum[part]
                let partStrLvl = partner.partStr[part] || 0
                let attriList = gameConfigHandle.gameConfig.partner.attriList
                let strengthenUp = gameConfigHandle.gameConfig.equipment.strengthenUp
                mainAttris.forEach(item => {
                    let attriName = item[0]
                    let upValues = attriList[attriName]
                    let attriValue = item[1]
                    if (player.gameSet.gameMode) {
                        attriValue = fighterHandle.calcQualityAddAttri(fighter, attriName, item[1])
                    }
                    let baseValue = attriValue * (1 + strengthenUp * equipment.equipment.strengthen)
                    baseValue = utils.floor(baseValue, 2)
                    fighter.attri[attriName] += Math.floor(baseValue * utils.getIncValue(upValues, partStrLvl * values[0]) * values[1] / 100)
                })
                //固定属性
                let fixedAttri = equipment.equipment.fixedAttri
                fixedAttri.forEach(item => {
                    fighter.attri[item[0]] += item[1]
                })

                //镶嵌的宝石属性
                let gems = equipment.equipment.gems
                if (gems) {
                    for (let i = 0; i < gems.length; i++) {
                        let gem = gems[i]
                        if (gem != null) {
                            let equipmentKind = gameConfigHandle.configByID[equipment.tID].equipmentKind
                            let part = equipmentHandle.equipmentKindToPart[equipmentKind]
                            let attri = equipmentHandle.getGemAttriOfPart(gem.tID, gem.hp, part)
                            fighter.attri[attri.attriName] += attri.attriValue
                        }
                    }
                }
                //随机属性
                let itemConfig = gameConfigHandle.configByID[equipment.tID]
                let subAttris = equipment.equipment.subAttris
                for (let i = 0; i < subAttris.length; i++) {
                    let attriType = subAttris[i][0]
                    let attriNameOrSkillID = subAttris[i][1]
                    let value = subAttris[i][2]
                    // 重构代码以修复潜在的bug
                    if (attriType == 'attri') {
                        // 确保属性存在
                        if (!fighter.attri[attriNameOrSkillID]) {
                            fighter.attri[attriNameOrSkillID] = 0;
                        }
                        fighter.attri[attriNameOrSkillID] += value;
                    } else if (attriType == 'reduceSkillCd' && (itemConfig.equipmentKind == EquipmentItemType.Hand || itemConfig.equipmentKind == EquipmentItemType.SubHand)) {
                        // 初始化技能冷却减少值
                        if (!fighter.skillsReduceCd[attriNameOrSkillID]) {
                            fighter.skillsReduceCd[attriNameOrSkillID] = 0;
                        }
                        fighter.skillsReduceCd[attriNameOrSkillID] += value;
                    } else if (attriType == 'addSkillHurt') {
                        // 初始化技能伤害增加值
                        if (!fighter.skillsHurtPer[attriNameOrSkillID]) {
                            fighter.skillsHurtPer[attriNameOrSkillID] = 0;
                        }
                        fighter.skillsHurtPer[attriNameOrSkillID] += value;
                    } else if (attriType == 'realHurt' || attriType == 'reduceHurt' || attriType == 'addSkillHurtPer' || attriType == 'antiRealHurt' || attriType == 'reduceAttackHurt' || attriType == 'reduceSkillHurt' || attriType == 'addAttackHurt' || attriType == 'bloodHp') {
                        // 对于直接影响fighter.attri的属性，确保属性存在并增加值
                        let attriValue = parseFloat(attriNameOrSkillID); // 确保attriNameOrSkillID是数字
                        if (isNaN(attriValue)) {
                            console.error('attriValue is not a number');
                            return;
                        }
                        if (!fighter.attri[attriType]) {
                            fighter.attri[attriType] = 0;
                        }
                        fighter.attri[attriType] += attriValue;
                    }
                }
            }
        })
    }

    getDefaultSkill(partner: PartnerModel, fighter: FighterModel) {
        let partnerConfig = gameConfigHandle.configByID[partner.tID]
        let skills = partnerConfig.skills || []
        skills.map((sid, i) => {
            let skill = new SkillModel()
            skill.skillID = sid
            skill.skillLvl = partner.skillLvls[skill.skillID] || 1
            skill.auxiliarySkills = []
            let idx = fighter.skills.findIndex(s => s.skillID == sid)
            if (idx == -1) {
                fighter.skills.push(skill)
            }
        })
    }

    getPriceOfPartner(partner: PartnerModel) {
        if (!partner) {
            return null
        }
        let partnerConfig = gameConfigHandle.gameConfig.partner
        let releaseGet = partnerConfig.releasePartnerGet
        let itemID = releaseGet.itemID
        let amount = utils.getIncValue(releaseGet.amount, partner.quality)
        return { itemID, amount }
    }

    attriScore(attriName: string, pId: number, customFeature: any = null) {
        let attriFeature = customFeature || gameConfigHandle.configByID[pId].attriFeature
        let score
        let baseNum = 0
        if ((attriName == 'attackSpeed' || attriName == 'maxHp') && attriFeature[attriName]) {
            baseNum = Math.floor(attriFeature[attriName] / 20)
            score = PartnerQualityRateText[baseNum]
        } else if (utils.getPerByAttri(attriName) == '%' && attriFeature[attriName]) {
            baseNum = Math.floor(attriFeature[attriName] / 5)
            score = PartnerQualityRateText[baseNum]
        } else if (attriFeature[attriName]) {
            baseNum = Math.floor(attriFeature[attriName])
            score = PartnerQualityRateText[baseNum]
        }
        if (baseNum > PartnerQualityRateText.length - 1) {
            baseNum = PartnerQualityRateText.length - 1
        }
        score = PartnerQualityRateText[baseNum]
        return score
    }

    getUnlockTeamPos(player: PlayerModel) {
        let unlockPos = []
        for (let i = 0; i < 10; i++) {
            let unlock = gameConfig.partner.teamPosLock[i]
            let isLock = gameUtils.isLimit(player, unlock)
            if (!isLock) {
                unlockPos.push(i)
            }
        }
        return unlockPos
    }

    activeLinkageRoles(player: PlayerModel, skillID: number, roles: number[]) {
        let activeRoles = { activeLvl: 0, skillID, roles }
        if (!roles || roles.length == 0) {
            return activeRoles
        }
        player.teamList.list.forEach(p => {
            if (p && roles.findIndex(r => r == p.tID) != -1 && p.star >= 3) {
                if (activeRoles[p.tID] && activeRoles[p.tID] < p.star) {
                    activeRoles[p.tID] = p.star
                } else if (p && !activeRoles[p.tID]) {
                    activeRoles[p.tID] = p.star
                }
            }
        })
        let lvlCount3 = 0, lvlCount5 = 0
        roles.forEach(r => {
            let star = activeRoles[r] || 0
            if (star >= 3) {
                lvlCount3 += 1
            }
            if (star == 5) {
                lvlCount5 += 1
            }
        })
        if (lvlCount5 == roles.length) {
            activeRoles.activeLvl = 2
        } else if (lvlCount3 + lvlCount5 >= roles.length) {
            activeRoles.activeLvl = 1
        }
        return activeRoles
    }
}

let partnerHandle = new PartnerHandle()
export default partnerHandle